<?php
declare (strict_types = 1);

namespace app\command;

use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use app\service\ImageCompressService;

class ImageCompress extends Command
{
    protected function configure()
    {
        // 指令配置
        $this->setName('image:compress')
            ->setDescription('图片压缩管理工具')
            ->addArgument('action', Argument::REQUIRED, '操作类型: test|batch|stats')
            ->addArgument('path', Argument::OPTIONAL, '图片路径或目录路径')
            ->addOption('quality', 'q', Option::VALUE_OPTIONAL, '压缩质量 (1-100)', 85)
            ->addOption('width', 'w', Option::VALUE_OPTIONAL, '最大宽度', 1920)
            ->addOption('height', 'h', Option::VALUE_OPTIONAL, '最大高度', 1920)
            ->addOption('output', 'o', Option::VALUE_OPTIONAL, '输出目录')
            ->addOption('recursive', 'r', Option::VALUE_NONE, '递归处理子目录');
    }

    protected function execute(Input $input, Output $output)
    {
        $action = $input->getArgument('action');
        $path = $input->getArgument('path');
        
        $compressService = new ImageCompressService();
        
        switch ($action) {
            case 'test':
                $this->testCompress($input, $output, $compressService);
                break;
            case 'batch':
                $this->batchCompress($input, $output, $compressService);
                break;
            case 'stats':
                $this->showStats($input, $output, $compressService);
                break;
            default:
                $output->writeln('<error>未知操作: ' . $action . '</error>');
                $this->showHelp($output);
                return;
        }
    }
    
    /**
     * 测试单张图片压缩
     */
    private function testCompress(Input $input, Output $output, ImageCompressService $service)
    {
        $path = $input->getArgument('path');
        if (!$path) {
            $output->writeln('<error>请指定图片路径</error>');
            return;
        }
        
        if (!file_exists($path)) {
            $output->writeln('<error>文件不存在: ' . $path . '</error>');
            return;
        }
        
        $output->writeln('<info>开始测试图片压缩...</info>');
        $output->writeln('文件: ' . $path);
        
        // 显示原始信息
        $originalSize = filesize($path);
        $imageInfo = getimagesize($path);
        if (!$imageInfo) {
            $output->writeln('<error>不是有效的图片文件</error>');
            return;
        }
        
        $output->writeln('原始大小: ' . $this->formatBytes($originalSize));
        $output->writeln('原始尺寸: ' . $imageInfo[0] . ' x ' . $imageInfo[1]);
        
        // 获取压缩统计
        $stats = $service->getCompressionStats($path);
        $output->writeln('需要压缩: ' . ($stats['needs_compression'] ? '是' : '否'));
        
        if ($stats['needs_compression']) {
            $output->writeln('推荐质量: ' . $stats['recommended_settings']['quality'] . '%');
        }
        
        // 执行压缩
        $quality = (int)$input->getOption('quality');
        $width = (int)$input->getOption('width');
        $height = (int)$input->getOption('height');
        
        $outputPath = $input->getOption('output');
        if (!$outputPath) {
            $outputPath = dirname($path) . '/compressed_' . basename($path);
        }
        
        $result = $service->compressImage($path, $outputPath, $quality, $width, $height);
        
        if ($result['success']) {
            if ($result['compressed']) {
                $output->writeln('<info>压缩成功!</info>');
                $output->writeln('压缩后大小: ' . $this->formatBytes($result['final_size']));
                $output->writeln('压缩比例: ' . $result['compression_ratio'] . '%');
                $output->writeln('使用质量: ' . $result['quality'] . '%');
                $output->writeln('输出文件: ' . $outputPath);
            } else {
                $output->writeln('<comment>图片无需压缩</comment>');
            }
        } else {
            $output->writeln('<error>压缩失败: ' . $result['error'] . '</error>');
        }
    }
    
    /**
     * 批量压缩图片
     */
    private function batchCompress(Input $input, Output $output, ImageCompressService $service)
    {
        $path = $input->getArgument('path');
        if (!$path) {
            $output->writeln('<error>请指定目录路径</error>');
            return;
        }
        
        if (!is_dir($path)) {
            $output->writeln('<error>目录不存在: ' . $path . '</error>');
            return;
        }
        
        $recursive = $input->getOption('recursive');
        $outputDir = $input->getOption('output') ?: $path . '/compressed';
        
        // 创建输出目录
        if (!is_dir($outputDir)) {
            mkdir($outputDir, 0755, true);
        }
        
        $output->writeln('<info>开始批量压缩...</info>');
        $output->writeln('源目录: ' . $path);
        $output->writeln('输出目录: ' . $outputDir);
        
        // 获取图片文件列表
        $imageFiles = $this->getImageFiles($path, $recursive);
        $total = count($imageFiles);
        
        if ($total === 0) {
            $output->writeln('<comment>未找到图片文件</comment>');
            return;
        }
        
        $output->writeln('找到 ' . $total . ' 个图片文件');
        
        $success = 0;
        $compressed = 0;
        $totalOriginalSize = 0;
        $totalFinalSize = 0;
        
        foreach ($imageFiles as $i => $file) {
            $progress = $i + 1;
            $output->write("处理 [{$progress}/{$total}] " . basename($file) . '... ');
            
            $outputFile = $outputDir . '/' . basename($file);
            $result = $service->compressImage($file, $outputFile);
            
            if ($result['success']) {
                $success++;
                $totalOriginalSize += $result['original_size'];
                $totalFinalSize += $result['final_size'];
                
                if ($result['compressed']) {
                    $compressed++;
                    $output->writeln('<info>压缩成功 (' . $result['compression_ratio'] . '%)</info>');
                } else {
                    $output->writeln('<comment>无需压缩</comment>');
                }
            } else {
                $output->writeln('<error>失败: ' . $result['error'] . '</error>');
            }
        }
        
        // 显示统计信息
        $output->writeln('');
        $output->writeln('<info>批量处理完成!</info>');
        $output->writeln('总文件数: ' . $total);
        $output->writeln('成功处理: ' . $success);
        $output->writeln('压缩文件: ' . $compressed);
        
        if ($totalOriginalSize > 0) {
            $totalSaved = $totalOriginalSize - $totalFinalSize;
            $totalRatio = round(($totalSaved / $totalOriginalSize) * 100, 2);
            $output->writeln('原始总大小: ' . $this->formatBytes($totalOriginalSize));
            $output->writeln('压缩后总大小: ' . $this->formatBytes($totalFinalSize));
            $output->writeln('节省空间: ' . $this->formatBytes($totalSaved) . ' (' . $totalRatio . '%)');
        }
    }
    
    /**
     * 显示统计信息
     */
    private function showStats(Input $input, Output $output, ImageCompressService $service)
    {
        $path = $input->getArgument('path');
        if (!$path) {
            $output->writeln('<error>请指定文件或目录路径</error>');
            return;
        }
        
        if (is_file($path)) {
            // 单文件统计
            $stats = $service->getCompressionStats($path);
            if (empty($stats)) {
                $output->writeln('<error>无法获取文件信息</error>');
                return;
            }
            
            $output->writeln('<info>图片统计信息</info>');
            $output->writeln('文件: ' . $path);
            $output->writeln('大小: ' . $stats['file_size_mb'] . ' MB');
            $output->writeln('尺寸: ' . $stats['dimensions']);
            $output->writeln('需要压缩: ' . ($stats['needs_compression'] ? '是' : '否'));
            $output->writeln('目标大小: ' . $stats['target_size_mb'] . ' MB');
            
            if ($stats['needs_compression']) {
                $settings = $stats['recommended_settings'];
                $output->writeln('推荐设置:');
                $output->writeln('  质量: ' . $settings['quality'] . '%');
                $output->writeln('  最大宽度: ' . $settings['maxWidth'] . 'px');
                $output->writeln('  最大高度: ' . $settings['maxHeight'] . 'px');
            }
            
        } else if (is_dir($path)) {
            // 目录统计
            $recursive = $input->getOption('recursive');
            $imageFiles = $this->getImageFiles($path, $recursive);
            
            $totalFiles = count($imageFiles);
            $totalSize = 0;
            $needsCompressionCount = 0;
            $oversizeCount = 0;
            
            foreach ($imageFiles as $file) {
                $stats = $service->getCompressionStats($file);
                if (!empty($stats)) {
                    $totalSize += $stats['file_size'];
                    if ($stats['needs_compression']) {
                        $needsCompressionCount++;
                    }
                    if ($stats['file_size'] > 2 * 1024 * 1024) { // 2MB
                        $oversizeCount++;
                    }
                }
            }
            
            $output->writeln('<info>目录统计信息</info>');
            $output->writeln('目录: ' . $path);
            $output->writeln('图片文件数: ' . $totalFiles);
            $output->writeln('总大小: ' . $this->formatBytes($totalSize));
            $output->writeln('需要压缩: ' . $needsCompressionCount . ' 个');
            $output->writeln('超过2MB: ' . $oversizeCount . ' 个');
            
            if ($totalFiles > 0) {
                $avgSize = $totalSize / $totalFiles;
                $output->writeln('平均大小: ' . $this->formatBytes($avgSize));
            }
        } else {
            $output->writeln('<error>路径不存在: ' . $path . '</error>');
        }
    }
    
    /**
     * 获取图片文件列表
     */
    private function getImageFiles(string $dir, bool $recursive = false): array
    {
        $files = [];
        $extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
        
        $iterator = $recursive ? 
            new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir)) :
            new \DirectoryIterator($dir);
        
        foreach ($iterator as $file) {
            if ($file->isFile()) {
                $ext = strtolower($file->getExtension());
                if (in_array($ext, $extensions)) {
                    $files[] = $file->getPathname();
                }
            }
        }
        
        return $files;
    }
    
    /**
     * 格式化字节大小
     */
    private function formatBytes(int $bytes, int $precision = 2): string
    {
        $units = ['B', 'KB', 'MB', 'GB'];
        
        for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) {
            $bytes /= 1024;
        }
        
        return round($bytes, $precision) . ' ' . $units[$i];
    }
    
    /**
     * 显示帮助信息
     */
    private function showHelp(Output $output)
    {
        $output->writeln('');
        $output->writeln('<comment>使用示例:</comment>');
        $output->writeln('  php think image:compress test /path/to/image.jpg');
        $output->writeln('  php think image:compress batch /path/to/images --output=/path/to/output');
        $output->writeln('  php think image:compress stats /path/to/images --recursive');
        $output->writeln('');
        $output->writeln('<comment>选项说明:</comment>');
        $output->writeln('  -q, --quality    压缩质量 (1-100)');
        $output->writeln('  -w, --width      最大宽度');
        $output->writeln('  -h, --height     最大高度');
        $output->writeln('  -o, --output     输出路径');
        $output->writeln('  -r, --recursive  递归处理子目录');
    }
}
